// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_

#include <wayland-client-core.h>

#include "base/memory/scoped_ptr.h"

struct wl_buffer;
struct wl_compositor;
struct wl_registry;
struct wl_shm;
struct wl_shm_pool;
struct wl_surface;
struct xdg_shell;
struct xdg_surface;

namespace wl {

template <typename T>
struct ObjectTraits;

template <>
struct ObjectTraits<wl_buffer> {
    static const wl_interface* interface;
    static void (*deleter)(wl_buffer*);
};

template <>
struct ObjectTraits<wl_compositor> {
    static const wl_interface* interface;
    static void (*deleter)(wl_compositor*);
};

template <>
struct ObjectTraits<wl_display> {
    static const wl_interface* interface;
    static void (*deleter)(wl_display*);
};

template <>
struct ObjectTraits<wl_registry> {
    static const wl_interface* interface;
    static void (*deleter)(wl_registry*);
};

template <>
struct ObjectTraits<wl_shm> {
    static const wl_interface* interface;
    static void (*deleter)(wl_shm*);
};

template <>
struct ObjectTraits<wl_shm_pool> {
    static const wl_interface* interface;
    static void (*deleter)(wl_shm_pool*);
};

template <>
struct ObjectTraits<wl_surface> {
    static const wl_interface* interface;
    static void (*deleter)(wl_surface*);
};

template <>
struct ObjectTraits<xdg_shell> {
    static const wl_interface* interface;
    static void (*deleter)(xdg_shell*);
};

template <>
struct ObjectTraits<xdg_surface> {
    static const wl_interface* interface;
    static void (*deleter)(xdg_surface*);
};

struct Deleter {
    template <typename T>
    void operator()(T* obj)
    {
        ObjectTraits<T>::deleter(obj);
    }
};

template <typename T>
class Object : public scoped_ptr<T, Deleter> {
public:
    Object() { }
    explicit Object(T* obj)
        : scoped_ptr<T, Deleter>(obj)
    {
    }

    uint32_t id()
    {
        return wl_proxy_get_id(
            reinterpret_cast<wl_proxy*>(scoped_ptr<T, Deleter>::get()));
    }
};

template <typename T>
wl::Object<T> Bind(wl_registry* registry, uint32_t name, uint32_t version)
{
    return wl::Object<T>(static_cast<T*>(
        wl_registry_bind(registry, name, ObjectTraits<T>::interface, version)));
}

} // namespace wl

#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OBJECT_H_
